<template>
  <div class="month-container">
    <div class="r-datebox">
      <div class="current-date">
        <el-icon @click="preMonth"><CaretLeft /></el-icon>
        <span>{{ dateFormat(data.current, 'yyyy年MM月') }}</span>
        <el-icon @click="nextMonth"><CaretRight /></el-icon>
        <span class="go-today" @click="goToday">今天</span>
      </div>
      <div class="main-box">
        <div class="week">
          <div class="week-item" v-for="(item,index) in data.weeks" :key="index">{{ item.label }}</div>
        </div>
        <div class="date">
          <div class="date-item"
               :class="{pre : index < data.preCount}"
               v-for="(item,index) in data.dates" :key="index"
               @click="dateClick(item,index)">
            <div :class="{'date-item-value':data.dateIndex === index,today:isToday(item)}">
              {{ item.day }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {defineEmits, defineProps, onBeforeMount, reactive} from 'vue'
import {CaretLeft, CaretRight} from "@element-plus/icons-vue"


const props = defineProps({
  id: ''
})
const emit = defineEmits(['change']);

const data = reactive({
  weeks: [
    {label: '日', value: 0},
    {label: '一', value: 1},
    {label: '二', value: 2},
    {label: '三', value: 3},
    {label: '四', value: 4},
    {label: '五', value: 5},
    {label: '六', value: 6},
  ],
  current: new Date(),
  dateIndex: 0,
  preCount: 0,
  dates: []
})

const goToday = () => {
  data.current = new Date()
  initDate()
}

/** 判断是否是当前日期 */
const isToday = ({date}) => {
  let itemDateStr = dateFormat(date, 'YYYY-MM-dd')
  let todayDateStr = dateFormat(Date.now(), 'YYYY-MM-dd')
  return itemDateStr === todayDateStr
}

/** 日期点击 **/
const dateClick = (item, index) => {
  data.dateIndex = index;
  emit('change', dateFormat(item.date), item.date)
}

/** 上一个月 **/
const preMonth = () => {
  let y = data.current.getFullYear()
  let m = data.current.getMonth()
  if (m === 0) {
    m = 11
    y -= 1
  } else {
    m -= 1
  }

  data.current.setFullYear(y)
  data.current.setMonth(m)

  initDate()
}

/** 下一个月 **/
const nextMonth = () => {
  let y = data.current.getFullYear()
  let m = data.current.getMonth()
  if (m === 11) {
    m = 0
    y += 1
  } else {
    m += 1
  }

  data.current.setFullYear(y)
  data.current.setMonth(m)

  initDate()
}

/** 获取上一个月，返回年月 **/
const getPreYearAndMonth = () => {
  let y = data.current.getFullYear()
  let m = data.current.getMonth()
  if (m === 0) {
    m = 11
    y = y - 1
  } else {
    m = m - 1
  }

  return [y, m]
}

/** 页面加载完成，初始化日期 **/
const initDate = () => {
  let y = data.current.getFullYear()
  let m = data.current.getMonth()
  getDates(y, m)
}

/** 渲染日期 **/
const getDates = (y, m) => {
  let length = getCountByMonth(y, m)
  data.dates = Array.from({length}, (_, i) => ({
    day: i + 1,
    date: new Date(y, m, i + 1)
  }))

  //填充最前面的日期格子
  getPreDays(y, m)
}

/** 填充最前面的日期格子 **/
const getPreDays = (y, m) => {
  //获取第一天星期几
  let week = getFirstDayWeek(y, m)
  //如果月份第一天不是周天，则需要向前填充日期
  if (week !== 0) {
    let list = []
    //获取上月总共天数
    let preMonthCount = getCountByMonth(y, m - 1)
    let end = preMonthCount - week
    let pre = getPreYearAndMonth()
    while (preMonthCount > end) {
      list.unshift({
        day: preMonthCount,
        date: new Date(pre[0], pre[1], preMonthCount)
      })
      preMonthCount--
    }

    data.preCount = list.length
    data.dates.unshift(...list)

    //获取当前日期所在的索引值
    let d = new Date()
    if (d.getFullYear() === y && d.getMonth() === m) {
      data.dateIndex = d.getDate() + week - 1
    } else {
      data.dateIndex = -1
    }
  }
}

/** 获取某年某月总共天数 **/
const getCountByMonth = (y, m) => {
  return new Date(y, m + 1, 0).getDate()
}

/** 获取某年某月第一天星期几 **/
const getFirstDayWeek = (y, m) => {
  return new Date(y, m, 1).getDay()
}

const dateFormat = (date, format) => {
  if (date) {
    date = date instanceof Date ? date : new Date(date);
    let o = {
      "M+": date.getMonth() + 1,                 //月份
      "d+": date.getDate(),                    //日
      "h+": date.getHours(),                   //小时
      "m+": date.getMinutes(),                 //分
      "s+": date.getSeconds(),                 //秒
      "q+": Math.floor((date.getMonth() + 3) / 3), //季度
      "S": date.getMilliseconds()             //毫秒
    };

    format = (format || 'yyyy-MM-dd hh:mm:ss').replace(/y+/i, date.getFullYear());
    for (let i in o) format = format.replace(new RegExp('(' + i + ')'), ('0' + o[i]).slice(-2));
    return format;
  }
  return '';
}

onBeforeMount(() => {
  initDate()
})
</script>

<style scoped lang="less">

.month-container{
  width: 33vw;
  height: 46.5vh;
  border-radius: 10px;
  box-shadow: 0 0 8px 8px lightgray;
  background-color: #fafafa;
  position: absolute;
  left: 65.5vw;
  top: 51.5vh;
  .r-datebox {
    font-size: var(--content-font-size);
    color: #555;
    padding: 1vh;
    width: calc(100% - 20px);
    .current-date {
      display: flex;
      align-items: center;
      justify-content: center;
      color: #778899;
      position: relative;
      margin-top: 2vh;
      margin-bottom: 5vh;
      font-size: 2.2vh;
      letter-spacing: 1px;
      i {
        cursor: pointer;
        &.next {
          transform: rotate(180deg);
        }
      }
      .go-today {
        position: absolute;
        right: 20px;
        cursor: pointer;
        color: rgb(72,145,255);
        font-size: 1.8vh;
      }
    }
    .main-box {
      .week {
        display: flex;
        margin-bottom: 10px;
        .week-item {
          color: #474747;
          width: calc(100% / 7);
          text-align: center;
          font-weight: 700;
        }
      }
      .date {
        display: flex;
        flex-wrap: wrap;
        .date-item {
          display: flex;
          align-items: center;
          justify-content: center;
          width: calc(100% / 7);
          height: 30px;
          line-height: 30px;
          text-align: center;
          cursor: pointer;
          color: var(--word-active-color);
          margin-top: 1.5vh;
          .date-item-value {
            position: relative;
            width: 30px;
            height: 30px;
            background: #B0E0E6;
            border-radius: 50%;
            color: #fff;
          }
          .today {
            position: relative;
            width: 30px;
            height: 30px;
            &:after {
              position: absolute;
              content: 'Today';
              transform: scale(.5);
              color: var(--box-bg-color-2);
              right: 0;
              top: -6px;
              width: 8px;
              height: 8px;
            }
          }
          &.pre {
            color: #bdbdbd;
          }
        }
      }
    }
  }
}
</style>